<template>
    <div>
        <button type="button" class="btn btn-xs btn-info" v-on:click="selectFile()">
            <i class="ace-icon fa fa-upload bigger-120">&nbsp;{{text}}</i>
        </button>&nbsp;
        <!--设置动态id，v-bind -- props-->
        <input class="hidden" v-on:change="uploadFile()" v-bind:id="fileId+'-input'"
               type="file" ref="file">

    </div>
</template>

<script>
    export default {
        name: "big-file-icon",
        props:{
            text:{
                default:'上传大文件'
            },
            fileId:{
                default:'file-upload'
            },
            //接收teacher的回调函数
            afterUpload:{
                type:Function,
                default: null
            },
            //暴露定义的文件上传类型
            suffixTag:{
                default:[]
            },
            //增加获取枚举类型，提交表单时使用
            use:{
                default:""
            },
            //vod准备，如果不传入分片大小，默认50kb
            shardSize: {
                default:50*1024
            },
            //调用后端服务地址，默认为oss-append
            url:{
                default:"oss-append-file"
            }
        },
        //data必须return，否则报错：vue 报错 data functions should return an object: 和 Cannot read property '__ob__' of undefined
        data:function () {
            return {

            }
        },
        methods:{
           /**
             * 大文件上传
             */
            uploadFile(){
                let _this=this;
                //使用表单方式提交图片：FormData()
                let formData=new window.FormData();
                console.log("程序进入上传");
                //获取file-icon变量,可以代替fileShard
                let fileIcon=_this.$refs.file.files[0];
                console.log(JSON.stringify(fileIcon));
                /**
                 *fileIcon-->  File {
                  __proto__: File
                  lastModified: 1576832376973
                  lastModifiedDate: Fri Dec 20 2019 16:59:36 GMT+0800 (中国标准时间)
                  name: "十二生肖片尾.mp4"
                  size: 28522823
                  type: "video/mp4"
                  webkitRelativePath: (...)

                  使用MD5信息摘要算法，常用于密码加密，生成128位二进制数，每4个二进制数 转换为 1个16进制数
                  返回结果：32个16进制数，32位字符串
                  1.引入md5：使用hex_md5进行file加密
                  2.将转换的key，转为十进制key10
                  3.将key10转换为62进制（26个大写字母+26个小写字母+10个阿拉伯数字=62个字符=62进制数）
                  4.需要更新fileService方法,做md5-id判断
                  5.必须将fileIcon的name、size、type传入，拼字符串，才能实现不同文件的MD5-code生成
                 */
                let keyMD=hex_md5(fileIcon.name+fileIcon.size+fileIcon.type);
                let key10=parseInt(keyMD,16);
                let key62=Tool.md_10to64(key10);
                console.log("keyMD: ",keyMD,"key10: ",key10,"key64: ",key62);
                /**
                 * keyMD:d41d8cd98f00b204e9800998ecf8427e
                 * key10:2.8194976848941264e+38
                 * key64:6sfSqfOwzmik4A4icMYuUe
                 */
                //判断文件格式
                //1.定义支持文件类型
                let suffixTag=_this.suffixTag;
                //2.获取图片文件名
                let fileName=fileIcon.name;
                //3.通过计算，获取后缀名
                let suffix=fileName.substring(fileName.lastIndexOf(".")+1,fileName.length).toLowerCase();
                //4.定义后缀校验变量
                let validateSuffix=false;
                for(let i=0;i<suffixTag.length;i++){
                    if(suffixTag[i].toLowerCase()===suffix){
                        //校验通过，结束当前程序
                        validateSuffix=true;
                        break;
                    }
                }
                if(!validateSuffix){
                    Toast.warning("文件格式不正确！只支持上传："+suffixTag.join(","));
                    //上传完毕，清空之前的数据，防止同一图片二次提交没有提示
                    $("#"+_this.fileId+"-input").val("");
                    return;
                }

                /**文件分片设置
                 * 每10M进行分片
                 * 根据实际上传数据，修改为50kb
                 */
                //let shardFileSize=50*1024;
                //更新vod后，采用默认分片大小
                let shardFileSize=_this.shardSize;

                //1.分片索引，1表示第一个分片
                let shardIndex=1;
                //5.从文件中截取当前的分片数据
                let size=fileIcon.size;
                //6.文件大小size / 每个分片的定值大小 = 总分片数
                let shardTotal=Math.ceil(size/shardFileSize);

                let fileParam={
                    'shardIndex':shardIndex,
                    'shardSize':shardFileSize,
                    'shardTotal':shardTotal,
                    'use':_this.use,
                    'name':fileIcon.name,
                    'suffix':suffix,
                    'size':fileIcon.size,
                    'fileKey':key62
                };
                //调用方法
                //_this.extracted(fileParam);
               //检查
               _this.checkFileKey(fileParam);
            },
            /**
             * 选择图片按钮
             */
            selectFile(){
                let _this=this;
                //$("#file-upload-input").trigger("click");
                $("#"+_this.fileId+"-input").trigger("click");
            },
            //except生成的方法
            extracted(fileParam) {
                let _this=this;
                let shardIndex=fileParam.shardIndex;
                let shardTotal=fileParam.shardTotal;
                let shardFileSize=fileParam.shardSize;
                //传入shardFile
                let shardFile = _this.extractedShardFile(shardIndex, shardFileSize);
                //1.将文件转为base64进行传输
                let fileReader = new FileReader();
                //上传之前显示进度条
                Progress.show(parseInt((shardIndex-1) * 100 / shardTotal));

                //2.增加onload事件监听
                fileReader.onload = function (e) {
                    let base64 = e.target.result;
                    //console.log("base64--> ",base64);
                    //使用@requestBody需要将formData的数据进行json绑定，这里的shardBase关联dto
                    fileParam.shardBase = base64;
                    //加入进度条，无需显示loading
                    //Loading.show();
                    //_this.$ajax.post(process.env.VUE_APP_SERVER + '/file/admin/teacher/upload-shard-base/',fileParam)

                    //OSS调取方法
                    //_this.$ajax.post(process.env.VUE_APP_SERVER + '/file/admin/oss-append-file/',fileParam)
                    //vod更新方法
                    _this.$ajax.post(process.env.VUE_APP_SERVER + '/file/admin/'+_this.url,fileParam)
                        .then((responseImg) => {
                            Loading.hide();
                            let response = responseImg.data;
                            //接收controller传来的responseData
                            console.log("上传文件成功-地址：", response);
                            //上传完第一个分片显示更新进度
                            Progress.show(parseInt(shardIndex*100/shardTotal));
                            /**
                             * 在上传结束，做判断，这里extract
                             * shardIndex=shardTotal=所有分片上传完毕
                             * shardIndex<shardTotal=继续上传下一个分片
                             */
                            if (shardIndex < shardTotal) {
                                //上传下一个分片shardIndex+1，再次截取base64
                                fileParam.shardIndex=fileParam.shardIndex+1;
                                //测试分片传输中断，断点续传
                                // if(fileParam.shardIndex===3){
                                //     return;
                                // }
                                _this.extracted(fileParam);
                            }else{
                                //分片传输完毕，隐藏进度条
                                Progress.hide();
                                _this.afterUpload(response);
                                //上传完毕，清空之前的数据，防止同一图片二次提交没有提示
                                $("#" + _this.fileId + "-input").val("");
                            }
                        });
                }
                fileReader.readAsDataURL(shardFile);
            },
            /**
             * 提取的shardFile
             * @param shardIndex
             * @param shardFileSize
             * @param fileIcon
             * @return {*}
             */
            extractedShardFile: function (shardIndex, shardFileSize) {
                let _this=this;
                let fileIcon=_this.$refs.file.files[0];
                //2.当前分片起始位置，由于起始索引为1，这里计算的start需要-1
                let start = (shardIndex - 1) * shardFileSize;
                //3.当前分片结束为止:起始位置+分片大小。如果计算得出start+shardFileSize>file.size，那么取文件大小size
                let end = Math.min(fileIcon.size, start + shardFileSize);
                //4.file剪切开始和结尾
                let shardFile = fileIcon.slice(start, end);
                return shardFile;
            },
            checkFileKey(fileParam){
                let _this=this;
                //_this.$ajax.get(process.env.VUE_APP_SERVER + '/file/admin/teacher/check-shard/'+fileParam.fileKey)
                //更新为vod查询
                _this.$ajax.get(process.env.VUE_APP_SERVER + '/file/admin/teacher/check-vod/'+fileParam.fileKey)
                .then((responseKey)=>{
                    let response=responseKey.data;
                    if (response.success){
                        let obj=response.responseData;
                        if(!obj){
                            fileParam.shardIndex=1;
                            console.log("没有找到分片记录，从1开始上传");
                            _this.extracted(fileParam);
                        }else if(obj.shardIndex===obj.shardTotal){
                            //shardIndex=shardToal
                            Toast.success("文件已急速秒传成功！");
                            _this.afterUpload(response);
                            $("#" + _this.fileId + "-input").val("");
                        }else{
                            fileParam.shardIndex=obj.shardIndex+1;
                            console.log("找到文件记录，从分片---"+fileParam.shardIndex+"---开始上传");
                            _this.extracted(fileParam);
                        }
                    }else{
                        Toast.warning("文件上传失败！");
                        $("#" + _this.fileId + "-input").val("");
                    }
                });
            },
        }
    }
</script>

<style scoped>

</style>